﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using PEProtocol;
using PEUtils;
using PNet;

public class NetSvc : ILogic
{
    private IOCPNet<LoginToken, NetMsg> mLoginNet;
    private IOCPNet<BattleToken, NetMsg> mBattleNet;
    private readonly Dictionary<CMD, Action<NetMsg>> mMsgDic = new Dictionary<CMD, Action<NetMsg>>();
    private ConcurrentQueue<NetMsg> mMsgQueue = new ConcurrentQueue<NetMsg>();
    private PERoot mRoot;

    /// <summary>
    /// 缓存请求后回应的网络数据包，例如ReqLogin是1，接收RspLogin2
    /// </summary>
    private readonly Dictionary<CMD, Action<NetMsg>> mRspMsgDic = new Dictionary<CMD, Action<NetMsg>>();

    public void Init()
    {
        this.Log("NetSvc.Init...");
        mRoot = PERoot.Instance;
        IOCPTool.LogFunc = (msg) => PELog.Log(msg);
        IOCPTool.WarningFunc = (msg) => PELog.Warn(msg);
        IOCPTool.ErrorFunc = (msg) => PELog.Error(msg);
        IOCPTool.ColorLogFunc = (color, msg) => { PELog.ColorLog((PEUtils.LogColor)color, msg); };

        AddMsgHandle(CMD.OnClient2LoginConnected, OnClient2LoginConnected);
        AddMsgHandle(CMD.OnClient2LoginDisconnected, OnClient2LoginDisconnected);
        AddMsgHandle(CMD.OnClient2BattleConnected, OnClient2BattleConnected);
        AddMsgHandle(CMD.OnClient2BattleDisconnected, OnClient2BattleDisconnected);
    }

    private void OnClient2BattleDisconnected(NetMsg obj)
    {
        this.LogYellow("Battle Client Disconnected...");
    }

    private void OnClient2BattleConnected(NetMsg obj)
    {
        this.LogGreen("Battle Client Connected...");
    }

    private void OnClient2LoginDisconnected(NetMsg obj)
    {
        this.LogYellow("Login Client Disconnected...");
    }

    private void OnClient2LoginConnected(NetMsg obj)
    {
        this.LogGreen("Login Client Connected...");
    }

    public void Tick()
    {
        while (!mMsgQueue.IsEmpty)
        {
            if (mMsgQueue.TryDequeue(out var msg))
            {
                if (mRspMsgDic.ContainsKey(msg.CMD)) //收到消息包，先判断是否为响应包
                {
                    mRspMsgDic[msg.CMD]?.Invoke(msg);
                }
                else //不是响应网络包，说明是通知网络包
                {
                    if (mMsgDic.ContainsKey(msg.CMD))
                    {
                        mMsgDic[msg.CMD]?.Invoke(msg);
                    }
                }
            }
        }
    }

    public void UnInit()
    {
        this.Log("NetSvc.UnInit...");
    }

    public void AddMsg(NetMsg msg)
    {
        mMsgQueue.Enqueue(msg);
    }

    public void AddMsgHandle(CMD cmd, Action<NetMsg> handler = null)
    {
        if (!mMsgDic.ContainsKey(cmd))
        {
            mMsgDic.Add(cmd, handler);
        }
        else
        {
            this.Log($"The dictionary contains this key:[{cmd}]!");
        }
    }

    public void StartConnectToLogin()
    {
        this.Log("NetSvc.ConnectToLogin...");
        mLoginNet = new IOCPNet<LoginToken, NetMsg>();
        mLoginNet.StartAsClient("192.168.0.100", 17888);
    }

    public void StartConnectToBattle()
    {
        this.Log("NetSvc.ConnectToBattle...");
        mBattleNet = new IOCPNet<BattleToken, NetMsg>();
        mBattleNet.StartAsClient(mRoot.AcctSystem.IP,mRoot.AcctSystem.Port);
    }

    /// <summary>
    /// 主动断开登录服的连接
    /// </summary>
    public void ActiveDisconnectToLogin()
    {
        mLoginNet.CloseClient();
    }

    /// <summary>
    /// 主动断开战斗的连接
    /// </summary>
    public void ActiveDisconnectToBattle()
    {
        mBattleNet.CloseClient();
    }

    /// <summary>
    /// 判断当前是否连接到战斗服
    /// </summary>
    /// <returns></returns>
    public bool IsConnectToBattle()
    {
        if (mBattleNet != null && mBattleNet.Token != null)
        {
            return mBattleNet.Token.IsConnected;
        }
        return false;

    }
    /// <summary>
    /// 判断当前是否连接到登录服
    /// </summary>
    /// <returns></returns>
    public bool IsConnectToLogin()
    {
        if (mLoginNet != null && mLoginNet.Token != null)
        {
            return mLoginNet.Token.IsConnected;
        }
        return false;

    }
    /// <summary>
    /// 发送网络消息
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="msgAction"></param>
    public void SendMsg(NetMsg msg, Action<NetMsg> msgAction = null)
    {
        if (msgAction != null)
        {
            CMD rspCMD = msg.CMD + 1;
            if (!mRspMsgDic.ContainsKey(rspCMD))
            {
                mRspMsgDic.Add(rspCMD, msgAction);
            }
            else
            {
                this.Warn($"The Cmd [{rspCMD}] is already exist!");
            }
        }

        switch (msg.CMD)
        {
            case CMD.ReqLogin:
            case CMD.ReqRoleToken:
                mLoginNet?.Token.SendMsg(msg);
                break;
            default:
                mBattleNet?.Token.SendMsg(msg);
                break;
        }
    }
}